﻿using Niknak.Services.ServiceCore;
using Niknak.Services.ServiceCore.Wcf;
using Niknak.Services.TaskScheduler.Wcf;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Text;

namespace Niknak.Services.TaskScheduler
{
    public class WcfEndpointHelper<WcfConfigurationSettings, ExceptionHandlerType> : Niknak.Services.ServiceCore.Wcf.Helper<WcfConfigurationSettings, Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient>
        where WcfConfigurationSettings : IWcfConfig, new()
        where ExceptionHandlerType : IExceptionHandler, new()
    {
        public static ExceptionHandlerType CustomExceptionHandler
        {
            get { return new ExceptionHandlerType(); }
        }

        public static bool IsEndpointOnline()
        {
            return EndpointAvailable;
        }

        public static Guid[] GetRunningTaskIds()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    Guid[] value = client.GetRunningTaskIds();
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return new Guid[0];
        }

        public static bool Reset()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    bool value = client.Reset();
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return false;
        }

        public static bool Restart()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    bool value = client.Restart();
                    client.Close(); //unlikely we'll get this far
                }
            }
            catch { } //some kind of error is expected since we're yanking the plug

            return true; //since the application exits before it gets a chance to respond, assume (!) it was all good
        }

        public static bool RaiseIterationCompletedEvent(Guid scheduledTaskId, DateTime iterationDate)
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    bool value = client.RaiseIterationCompletedEvent(scheduledTaskId, iterationDate);
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return false;
        }

        public static long GetServiceUptime()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    long value = client.GetServiceUptime();
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return 0;
        }

        public static long GetEndpointUptime()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    long value = client.GetEndpointUptime();
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return 0;
        }
        public static string GetCustomEventLogName()
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    string value = client.GetCustomEventLogName();
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return string.Empty;
        }

        public static SerializableEventRecord[] ReadFromEventLog(string logName, InternalEnums.EventLogLevel[] logLevels, string providerName, DateTime afterTimestamp, DateTime beforeTimestamp, int skip, int take)
        {
            Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient client = new Niknak.Services.TaskScheduler.Wcf.RemoteTaskScheduler.WcfEndpointClient();
            try
            {
                if (EndpointAvailable)
                {
                    SerializableEventRecord[] value = client.ReadFromEventLog(logName, logLevels, providerName, afterTimestamp, beforeTimestamp, skip, take);
                    client.Close();
                    return value;
                }
            }
            catch (Exception ex)
            {
                CustomExceptionHandler.ExceptionLogEntry(ex);
                ex.GetHashCode();
                if (client.State == System.ServiceModel.CommunicationState.Faulted)
                    client.Abort();
                else
                    client.Close();
            }

            return null;
        }
    }
}
